home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / DJGPP / CBGRX103.ZIP / contrib / libgrx / src / thicklne.c < prev    next >
Text File  |  1993-12-06  |  6KB  |  230 lines

  1. /**
  2.  ** THICKLNE.C
  3.  **
  4.  **  Copyright (C) 1992, Csaba Biegl
  5.  **    820 Stirrup Dr, Nashville, TN, 37221
  6.  **    csaba@vuse.vanderbilt.edu
  7.  **
  8.  **  This file is distributed under the terms listed in the document
  9.  **  "copying.cb", available from the author at the address above.
  10.  **  A copy of "copying.cb" should accompany this file; if not, a copy
  11.  **  should be available from where this file was obtained.  This file
  12.  **  may not be distributed without a verbatim copy of "copying.cb".
  13.  **  You should also have received a copy of the GNU General Public
  14.  **  License along with this program (it is in the file "copying");
  15.  **  if not, write to the Free Software Foundation, Inc., 675 Mass Ave,
  16.  **  Cambridge, MA 02139, USA.
  17.  **
  18.  **  This program is distributed in the hope that it will be useful,
  19.  **  but WITHOUT ANY WARRANTY; without even the implied warranty of
  20.  **  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21.  **  GNU General Public License for more details.
  22.  **/
  23.  
  24. #include "grx.h"
  25. #include "libgrx.h"
  26. #include "clipping.h"
  27. #include "thicklne.h"
  28.  
  29. void _GrBuildCustomLineData(GrLineOption *opt,GrCustomLineData *where)
  30. {
  31.     int total,ii;
  32.  
  33.     where->opt = *opt;
  34.     if(opt->lno_pattlen > 1) {
  35.         for(total = 0,ii = opt->lno_pattlen; --ii >= 0; total += opt->lno_dashpat[ii]);
  36.         where->total_pattlen = total;
  37.         where->next_sect     = 0;
  38.         where->cursect_left  = 0;
  39.         where->drawn_sect     = FALSE;
  40.     }
  41.     else where->total_pattlen = 0;
  42. }
  43.  
  44. extern void _GrDoCustomSegment(int x1,int y1,int x2,int y2,void *arg)
  45. {
  46. #define DIAG(x,y)    ((x)*(x) + (y)*(y))
  47.  
  48.     GrCustomLineData *dta = (GrCustomLineData *)arg;
  49.     int dx1,dy1,dx2,dy2;        /* offsets to corner points of thick line segment */
  50.     int sx1,sx2,sy1,sy2,length;    /* line segment length and end points */
  51.     int pts[4][2];            /* polygon corner points */
  52.     int dx = x2 - x1;
  53.     int dy = y2 - y1;
  54.     int wdt = dta->opt.lno_width;
  55.     int Xmajor = (IABS(dx) > IABS(dy)) ? TRUE : FALSE;
  56.     int done;
  57.  
  58.     if(wdt > 1) {
  59.         int wsq = wdt * wdt;
  60.         if(dx == 0) {
  61.         dy2 = 0;
  62.         dx2 = wdt;
  63.         }
  64.         else if(dy == 0) {
  65.         dx2 = 0;
  66.         dy2 = wdt;
  67.         }
  68.         else if(Xmajor) {
  69.         dy1 = ((7 * wdt) / 10) - 1;    /* at least !! (tangent is less than 45 deg) */
  70.         dx1 = -(dy1 * dy) / dx;        /* scale according to slope */
  71.         for( ; ; ) {
  72.             dy2 = dy1 + 1;
  73.             dx2 = -(dy2 * dy) / dx;
  74.             if(DIAG(dx2,dy2) > wsq) break;
  75.             dx1 = dx2;
  76.             dy1 = dy2;
  77.         }
  78.         if((DIAG(dx2,dy2) - wsq) > (wsq - DIAG(dx1,dy1))) {
  79.             dx2 = dx1;
  80.             dy2 = dy1;
  81.         }
  82.         }
  83.         else {
  84.         dx1 = ((7 * wdt) / 10) - 1;    /* at least !! (tangent is more than 45 deg) */
  85.         dy1 = -(dx1 * dx) / dy;        /* scale according to slope */
  86.         for( ; ; ) {
  87.             dx2 = dx1 + 1;
  88.             dy2 = -(dx2 * dx) / dy;
  89.             if(DIAG(dx2,dy2) > wsq) break;
  90.             dx1 = dx2;
  91.             dy1 = dy2;
  92.         }
  93.         if((DIAG(dx2,dy2) - wsq) > (wsq - DIAG(dx1,dy1))) {
  94.             dx2 = dx1;
  95.             dy2 = dy1;
  96.         }
  97.         }
  98.         dx1 = dx2 >> 1;
  99.         dy1 = dy2 >> 1;
  100.         dx2 = dx1 - dx2;
  101.         dy2 = dy1 - dy2;
  102.     }
  103.     if((dta->total_pattlen == 0) || ((dx == 0) && (dy == 0))) {
  104.         if(wdt <= 1) {
  105.         (*dta->borderproc)(x1,y1,x2,y2,dta->fillarg);
  106.         return;
  107.         }
  108.         pts[0][0] = x1 + dx1;
  109.         pts[0][1] = y1 + dy1;
  110.         pts[1][0] = x1 + dx2;
  111.         pts[1][1] = y1 + dy2;
  112.         pts[2][0] = x2 + dx2;
  113.         pts[2][1] = y2 + dy2;
  114.         pts[3][0] = x2 + dx1;
  115.         pts[3][1] = y2 + dy1;
  116.         _GrScanConvexPoly(4,pts,
  117.         dta->is_XOR_color,
  118.         dta->pixelproc,
  119.         dta->borderproc,
  120.         dta->scanfillproc,
  121.         dta->fillarg
  122.         );
  123.         return;
  124.     }
  125.     sx1 = x1;
  126.     sy1 = y1;
  127.     done = FALSE;
  128.     while(!done) {
  129.         if((length = dta->cursect_left) == 0) do {
  130.         if(dta->next_sect == dta->opt.lno_pattlen) {
  131.             dta->next_sect  = 0;
  132.             dta->drawn_sect = FALSE;
  133.         }
  134.         length = dta->opt.lno_dashpat[dta->next_sect++];
  135.         dta->drawn_sect ^= 1;
  136.         } while(length == 0);
  137.         else dta->cursect_left = 0;
  138.         if(Xmajor) {
  139.         if(dx < 0) {
  140.             if((sx2 = sx1 - length) <= x2) {
  141.             dta->cursect_left = x2 - sx2;
  142.             length = sx1 - (sx2 = x2);
  143.             done = TRUE;
  144.             }
  145.             else sx2++;
  146.         }
  147.         else {
  148.             if((sx2 = sx1 + length) >= x2) {
  149.             dta->cursect_left = sx2 - x2;
  150.             length = (sx2 = x2) - x1;
  151.             done = TRUE;
  152.             }
  153.             else sx2--;
  154.         }
  155.         sy1 = y1 + (((sx1 - x1) * dy) / dx);
  156.         sy2 = y1 + (((sx2 - x1) * dy) / dx);
  157.         }
  158.         else {
  159.         if(dy < 0) {
  160.             if((sy2 = sy1 - length) <= y2) {
  161.             dta->cursect_left = y2 - sy2;
  162.             length = sy1 - (sy2 = y2);
  163.             done = TRUE;
  164.             }
  165.             else sy2++;
  166.         }
  167.         else {
  168.             if((sy2 = sy1 + length) >= y2) {
  169.             dta->cursect_left = sy2 - y2;
  170.             length = (sy2 = y2) - y1;
  171.             done = TRUE;
  172.             }
  173.             else sy2--;
  174.         }
  175.         sx1 = x1 + (((sy1 - y1) * dx) / dy);
  176.         sx2 = x1 + (((sy2 - y1) * dx) / dy);
  177.         }
  178.         if(dta->drawn_sect && (length > 0)) {
  179.         if(wdt <= 1)
  180.             (*dta->borderproc)(sx1,sy1,sx2,sy2,dta->fillarg);
  181.         else {
  182.             pts[0][0] = sx1 + dx1;
  183.             pts[0][1] = sy1 + dy1;
  184.             pts[1][0] = sx1 + dx2;
  185.             pts[1][1] = sy1 + dy2;
  186.             pts[2][0] = sx2 + dx2;
  187.             pts[2][1] = sy2 + dy2;
  188.             pts[3][0] = sx2 + dx1;
  189.             pts[3][1] = sy2 + dy1;
  190.             _GrScanConvexPoly(4,pts,
  191.             dta->is_XOR_color,
  192.             dta->pixelproc,
  193.             dta->borderproc,
  194.             dta->scanfillproc,
  195.             dta->fillarg
  196.             );
  197.         }
  198.         }
  199.         if(Xmajor) {
  200.         if(dx < 0) sx1 -= length;
  201.         else       sx1 += length;
  202.         }
  203.         else {
  204.         if(dy < 0) sy1 -= length;
  205.         else       sy1 += length;
  206.         }
  207.     }
  208. }
  209.  
  210. extern void _GrDoSingleCustomSegment(int x1,int y1,int x2,int y2,GrCustomLineData *dta)
  211. {
  212.     int minx = x1,maxx = x2;
  213.     int miny = y1,maxy = y2;
  214.     MOUSE_FLAG;
  215.  
  216.     SORT2(minx,maxx);
  217.     SORT2(miny,maxy);
  218.     if(dta->opt.lno_width > 1) {
  219.         minx -= dta->opt.lno_width;
  220.         maxx += dta->opt.lno_width;
  221.         miny -= dta->opt.lno_width;
  222.         maxy += dta->opt.lno_width;
  223.     }
  224.     CLIPSORTEDBOX(CURC,minx,miny,maxx,maxy);
  225.     MOUSE_BLOCK(CURC,minx,miny,maxx,maxy);
  226.     _GrDoCustomSegment(x1,y1,x2,y2,dta);
  227.     MOUSE_UNBLOCK();
  228. }
  229.  
  230.